package com.impetus.project.skilltest.client.pages;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.impetus.project.skilltest.client.stub.TestService;
import com.impetus.project.skilltest.client.stub.TestServiceAsync;
import com.impetus.project.skilltest.common.Constants;
import com.impetus.project.skilltest.common.SkillTestException;
import com.impetus.project.skilltest.common.dataobject.ScheduledTest;

public class TestListingPage 
{
	private static final TestServiceAsync testService = GWT.create(TestService.class); 
	private ScheduledTest selectedTest = null;
	private DateTimeFormat sdfOutput = DateTimeFormat.getFormat("MM/dd/yyyy"); 
	private Label statusLabel = new Label();
	private int totalTestCount = 0;
	
	public void loadPage(final PageData pageData)throws SkillTestException
	{
		try
		{
			testService.getScheduledTests(pageData.getUser(), new AsyncCallback <List<ScheduledTest>>() {
				public void onSuccess(List<ScheduledTest> result) {
					drawScheduledTestTable(result, pageData);
				}
				public void onFailure(Throwable caught) {
					pageData.setExceptionCaught(caught);
				}
			});
			if(pageData.getExceptionCaught() != null){
				throw pageData.getExceptionCaught();
			}
		}
		catch(Throwable t)
		{
			if(t instanceof SkillTestException){
				throw (SkillTestException)t;
			}else{
				throw new SkillTestException(t);
			}
		}
	}
	
	private  void drawScheduledTestTable(List<ScheduledTest> list, final PageData pageData)
	{
		final HashMap<String, List<ScheduledTest>> hmTests = splitTestDataByStatus(list);
		final FlexTable flexTable = new FlexTable();
		
		flexTable.setCellSpacing(5);
	    flexTable.setCellPadding(3);
	    createHeader(flexTable);
	    totalTestCount = list.size();
	    
				
		if(hmTests.get(Constants.TEST_STATUS.RUNNING) != null
			&& hmTests.get(Constants.TEST_STATUS.RUNNING).size() > 0){
			addRowsToTable(hmTests.get(Constants.TEST_STATUS.RUNNING), flexTable);
		}
		if(hmTests.get(Constants.TEST_STATUS.SCHEDULED) != null
			&& hmTests.get(Constants.TEST_STATUS.SCHEDULED).size() > 0){
			addRowsToTable(hmTests.get(Constants.TEST_STATUS.SCHEDULED), flexTable);
		}
		if(flexTable.getRowCount() < 2){
			drawScheduledTestTableImpl(list, flexTable);
		}
		
		final Button statusButtons[] = new Button[8];
		statusButtons[0] = new Button(Constants.TEST_STATUS.ALL, new ClickHandler() {
			public void onClick(ClickEvent event) {
				drawScheduledTestTableImpl(hmTests.get(Constants.TEST_STATUS.ALL), flexTable);
			}});
		statusButtons[1] = new Button(Constants.TEST_STATUS.SCHEDULED, new ClickHandler() {
			public void onClick(ClickEvent event) {
				drawScheduledTestTableImpl(hmTests.get(Constants.TEST_STATUS.SCHEDULED), flexTable);
			}});
		statusButtons[2] = new Button(Constants.TEST_STATUS.STARTED, new ClickHandler() {
			public void onClick(ClickEvent event) {
				drawScheduledTestTableImpl(hmTests.get(Constants.TEST_STATUS.STARTED), flexTable);
			}});
		statusButtons[3] = new Button(Constants.TEST_STATUS.RUNNING, new ClickHandler() {
			public void onClick(ClickEvent event) {
				drawScheduledTestTableImpl(hmTests.get(Constants.TEST_STATUS.RUNNING), flexTable);
			}});
		statusButtons[4] = new Button(Constants.TEST_STATUS.ON_HOLD, new ClickHandler() {
			public void onClick(ClickEvent event) {
				drawScheduledTestTableImpl(hmTests.get(Constants.TEST_STATUS.ON_HOLD), flexTable);
			}});
		statusButtons[5] = new Button(Constants.TEST_STATUS.FINISHED, new ClickHandler() {
			public void onClick(ClickEvent event) {
				drawScheduledTestTableImpl(hmTests.get(Constants.TEST_STATUS.FINISHED), flexTable);
			}});
		statusButtons[6] = new Button(Constants.TEST_STATUS.ABORTED, new ClickHandler() {
			public void onClick(ClickEvent event) {
				drawScheduledTestTableImpl(hmTests.get(Constants.TEST_STATUS.ABORTED), flexTable);
			}});
		statusButtons[7] = new Button(Constants.TEST_STATUS.EXPIRED, new ClickHandler() {
			public void onClick(ClickEvent event) {
				drawScheduledTestTableImpl(hmTests.get(Constants.TEST_STATUS.EXPIRED), flexTable);
			}});
		
		final HorizontalPanel statusButtonPanel = new HorizontalPanel();
		for(Button but : statusButtons){
			statusButtonPanel.add(but);
		}
		
		final HorizontalPanel submitButtonPanel = new HorizontalPanel();
		if(pageData.getUser().getIsAdmin()){
			Button button = new Button("Schedule new test");
			button.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					pageData.setTest(null);
					PageRouter.loadPage(GUIConstants.PAGES.TEST_EDIT_PAGE, pageData);
				}});
			submitButtonPanel.add(button);
			
			button = new Button("View Report");
			button.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					pageData.setTest(selectedTest);
					PageRouter.loadPage(GUIConstants.PAGES.TEST_SUMMARY_PAGE, pageData);
				}});
			submitButtonPanel.add(button);
			
			button = new Button("Edit");
			button.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					pageData.setTest(selectedTest);
					PageRouter.loadPage(GUIConstants.PAGES.TEST_EDIT_PAGE, pageData);
				}});
			submitButtonPanel.add(button);
			
			submitButtonPanel.add(new Button("Delete"));
			// TODO: delete test
		}
		Button button1 = new Button("Participate");
		button1.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				try{
					pageData.setTest(selectedTest);
					PageRouter.loadPage(GUIConstants.PAGES.TEST_PARTICIPATION_PAGE, pageData);
				}catch(Throwable caught){
					pageData.setExceptionCaught(caught);
					new ErrorPage().loadPage(pageData);
				}
			}});
		submitButtonPanel.add(button1);
		
		HorizontalPanel menuPanel = TopMenu.drawMenu(pageData);
		
		final VerticalPanel vpanel = new VerticalPanel();
		vpanel.addStyleName("center");
		vpanel.add(menuPanel);
		vpanel.add(statusButtonPanel);
		vpanel.add(statusLabel);
		vpanel.add(flexTable);
		vpanel.add(submitButtonPanel);
		
		RootPanel.get().clear();
	    RootPanel.get().add(vpanel);
	}
	
	// must show scheduled and running tests on startup
	private  void drawScheduledTestTableImpl(List<ScheduledTest> list, FlexTable flexTable)
	{
		int flexTableSize = flexTable.getRowCount();
		for (int i=1; i<flexTableSize; i++){
			flexTable.removeRow(i);
		}
		
		statusLabel.setText("Listing tests: "+list.size()+" of "+totalTestCount);
		addRowsToTable(list, flexTable);
	}
	
	private void addRowsToTable(List<ScheduledTest> list, FlexTable flexTable)
	{
		if(list == null || list.size() == 0){
			return;
		}
		int length = list.size();
		for(int i=0; i<length; i++){
			int rowNum = flexTable.getRowCount();
			final ScheduledTest test = list.get(i);
			RadioButton rb0 = new RadioButton("RadioGroup");
			rb0.addClickHandler(new ClickHandler() {				
				public void onClick(ClickEvent event) {
					selectedTest = test;
				}
			});
			
			flexTable.setWidget(rowNum, 0, rb0);
			flexTable.setText(rowNum, 1, test.getCandidateid());
			flexTable.setText(rowNum, 2, test.getqType());
			flexTable.setText(rowNum, 3, test.getStatus());
			flexTable.setText(rowNum, 4, String.valueOf(test.getTestDurationMins()));
			flexTable.setText(rowNum, 5, String.valueOf(test.getQuestionCount()));
			flexTable.setText(rowNum, 6, test.getComplexity());
			flexTable.setText(rowNum, 7, String.valueOf(test.getScore()));
			flexTable.setText(rowNum, 8, sdfOutput.format(test.getModifiedon()));
		}
	}
	
	private void createHeader(FlexTable flexTable)
	{
		flexTable.removeAllRows();
		
		flexTable.setText(0, 0, "");
		flexTable.setText(0, 1, "Candidate");
		flexTable.setText(0, 2, "Type");
		flexTable.setText(0, 3, "Status");
		flexTable.setText(0, 4, "Duration in minutes");
		flexTable.setText(0, 5, "Question Count");
		flexTable.setText(0, 6, "Complexity");
		flexTable.setText(0, 7, "Score");
		flexTable.setText(0, 8, "Last Modified");
	}
	
	private HashMap<String, List<ScheduledTest>> splitTestDataByStatus(List<ScheduledTest> list)
	{
		HashMap<String, List<ScheduledTest>> hmTests = new HashMap<String, List<ScheduledTest>>();
		hmTests.put(Constants.TEST_STATUS.ALL, list);
		if(list == null || list.size() == 0){
			return hmTests;
		}
		
		Iterator<ScheduledTest> iter = list.iterator();
		while(iter.hasNext())
		{
			ScheduledTest test = iter.next();
			List<ScheduledTest> tmpList = hmTests.get(test.getStatus());
			if(tmpList == null){
				tmpList = new ArrayList<ScheduledTest>();
				hmTests.put(test.getStatus(), tmpList);
			}
			tmpList.add(test);
		}
		
		return hmTests;
	}
}
